package otest;

import processing.core.*; 

import java.util.List;
import java.util.ArrayList; 

import twitter4j.*;
import twitter4j.conf.ConfigurationBuilder; 

public class TwitterMultiTest extends PApplet {

    private static final long serialVersionUID = 1;
	
int locationCount = 0;
int nullCount = 0;

ArrayList<String> msgs = new ArrayList<String>();
ArrayList<GeoLocation> geoPoints = new ArrayList<GeoLocation>();

GeoLocation searchLocation = new GeoLocation(43.395132, -80.324993);
Double hundoRadius = 10.0; // radius, in kilometers as specified below	      
Query galt = new Query(); // this is what we'll search for, uses Query object
	
	public ArrayList<Status> buildTweets() { 
		println("running buildTweets");
		ArrayList<Status> tweets = new ArrayList<Status>();
	      ConfigurationBuilder cb = new ConfigurationBuilder();
	      cb.setOAuthConsumerKey("1joTbvy2N5iowiJkvMPoQ");
	      cb.setOAuthConsumerSecret("IjkHewjxLJB6x8pH1Y01MTKBw05btAN7WeXUITeoVY");
	      cb.setOAuthAccessToken("5451722-tSdcgntgBCPrwi9TEmADWTvNw4VyFVbuSSoHnQPY4S");
	      cb.setOAuthAccessTokenSecret("h3e9Ve3IwRAj2Gle8sTtir6ddyd5WddyKabuiWlrsPhlP");
	      
	      // this is a twitter object, it does the twitter things
	      Twitter twitter = new TwitterFactory(cb.build()).getInstance();
	      
	      galt.setCount(100); // search for all the tweets, max 100/page
	      galt.setGeoCode(searchLocation, hundoRadius, Query.KILOMETERS); // (geoLocation, double radius, unit for radius);
	      galt.setSince("2014-05-8");
	      
	      ArrayList<String> msgs = new ArrayList<String>();
	      
	      // sometimes this will not work, try/catch loop handles the exception it throws. neat.
	      try {
	    	  QueryResult result = twitter.search(galt);
	    	  List<Status> pageTweets = result.getTweets();
	    	  tweets.addAll(pageTweets);
	    	  int i = 0;
	    	  
	    	  	while (result.hasNext() == true){
	    	  		result = twitter.search(result.nextQuery()); // iterate to next page
	    	  		println("pages: " + i); // and let me know
	    	  		i += 1;
	    	  		pageTweets = result.getTweets(); // tweets is your list of all tweets from QueryResult, 
	    	  		tweets.addAll(pageTweets);
	    	  		if (i > 5) {
	    	  			break;
	    	  		}
	    	  	}
	    	  // now have ArrayList<Status> of all pages - or should
 
	    	 for (int x=0; x<tweets.size(); x++) { // this loop write the output for testing
	    		 println("locations");
	    		  Status tweet = tweets.get(x); 			// 'tweets.get' gets tweet by index : now you have the TweetEntity at index i
	    		  String tweettext = tweet.getText();		// now pull text
	    		  GeoLocation tweetlocate = tweet.getGeoLocation(); // pull location
	    		  try { 									// a lot of tweets don't have location data, use this to catch nulls
	    		  String tweetlatstr = Double.toString(tweetlocate.getLatitude());
	    		  String tweetlongstr = Double.toString(tweetlocate.getLongitude());
	    		  msgs.add(" | " + tweetlatstr + " | " + tweetlongstr + " | " + tweettext);
	    		  locationCount = locationCount + 1;
	    		  } catch (NullPointerException e) {
	    			  println("nulls");
	    			  String tweetlatstr = "| no lat ";
	    			  String tweetlongstr = " no long | "; // most are null.... try pagination until you hit results?
	    			  msgs.add(tweetlatstr + " | " + tweetlongstr + tweettext);
	    			  nullCount = nullCount + 1;
	    		  }
	    	 	}
	    	 msgs.add("test string");
	      }
	      catch (TwitterException te) {
	    	  String errormsg = "Couldn't connect: " + te;
	    	  msgs.add(errormsg);
	      }
	      println("tweets.size() at end of buildTweets: " + tweets.size());
	      return tweets;
	}
	
	public double[] getLatiEndPoints(GeoLocation location) {
		double lati = location.getLatitude(); // vertical mark Y
		double[] latiEndPoints = new double[2];
		latiEndPoints[0] = lati - hundoRadius/111.132;
		latiEndPoints[1] = lati + hundoRadius/111.132;
		return latiEndPoints;
	}
	
	public double[] getLongiEndPoints(GeoLocation location) {
		double longi = location.getLongitude(); // vertical mark Y
		double[] longiEndPoints = new double[2];
		longiEndPoints[0] = longi - hundoRadius/78.847; // there should really be much fancier math here, distance between longitudes changes as latitude changes
		longiEndPoints[1] = longi + hundoRadius/78.847;
		return longiEndPoints;
	}
	
/*	public void cullNoGeo() {
		ArrayList<Boolean> locationCheck = new ArrayList<Boolean>(tweets.size());
		// go through tweets and drop all sans location
		for(int i = 0; i < tweets.size(); i++) {
			Status tweet = tweets.get(i);
			try {
				String tweetlatstr = Double.toString(tweet.getGeoLocation().getLatitude());
				locationCheck.add(i, true);
				println(tweetlatstr);
			}
			catch (NullPointerException e) {
				locationCheck.add(i, false);
				println("bail");
			}
		}
		tweets.removeAll(locationCheck);
		println("running Cull");
	} */
	
	
	public ArrayList<PVector> buildPoints(ArrayList<Status> tweets) {
		ArrayList<PVector> mappedPoints = new ArrayList<PVector>();
		println("tweets.size() outside of buildTweets()" + tweets.size());
		println("buildPoints");
		for (int i = 0; i < tweets.size(); i++) {
			try {
				Status tweet = tweets.get(i);
				GeoLocation tweetGeo = tweet.getGeoLocation();
				float lati = (float) tweetGeo.getLatitude();
				float longi = (float) tweetGeo.getLongitude();
				float latiMap = map(lati,(float)getLatiEndPoints(searchLocation)[0],(float)getLatiEndPoints(searchLocation)[1],0,height); //(float) tweetGeo.getLatitude(); // how to convert?
				float longiMap = map(longi,(float)getLongiEndPoints(searchLocation)[0],(float)getLongiEndPoints(searchLocation)[1],0,width);
				PVector tweetPoint = new PVector(longiMap,latiMap);
				mappedPoints.add(tweetPoint);
				println(tweetPoint.x,tweetPoint.y);
			}
			catch (NullPointerException e) {
				println("location Null at: " + i);
			}
		} // now finish the mapping (keep it parametric) and throw them down in draw. try pasting text beside them following.
		return mappedPoints;
	}
	
	public ArrayList<String> buildMessages(ArrayList<Status> tweets) {
		ArrayList<String> msgs = new ArrayList<String>();
		for (int i = 0; i<tweets.size(); i++) {
			try {
				Status tweet = tweets.get(i);
				GeoLocation tweetGeo = tweet.getGeoLocation();
				float lati = (float) tweetGeo.getLatitude();
				String tweetMsg = tweet.getText();
				msgs.add(tweetMsg);
			}
			catch (NullPointerException e) {
				println("msgs location Null at: " + i);
			}
		}
		return msgs;
	}
	
	public void setup() {
		println("Running setup");

		size(700,700);
		background(0);
		stroke(255);
		println("Finished setup");
	}
	
	public void draw() { // pull out # of locations, # of nulls
		ArrayList<Status> tweets = buildTweets();
		PImage bg;
		bg = loadImage("/Users/Jake/cswork/on-the-line/OnTheLine/src/otest/mapBG.png");
		println("Running Draw");
		ArrayList<PVector> mappedPoints = buildPoints(tweets);
		println(mappedPoints.size());
		ArrayList<String> msgs = buildMessages(tweets);
		println(msgs.size());
		textSize(11);
		text("cachedout2", 60,40); // applet runs an older version of itself...
		text("# of: " + msgs.size() + " | locations: " + locationCount + " | culled tweets: " + mappedPoints.size() + " | nulls: " + nullCount, 60,80); // wherein buildTweets() should return msg ...
		for (int i = 0; i < msgs.size(); i++) {
			text(msgs.get(i), mappedPoints.get(i).x, mappedPoints.get(i).y);
		} 
		ellipse(width/2,height/2,10,10);
		text("mappedPoints.size()  :" + mappedPoints.size(), 60,120);
		for (int i = 0; i < mappedPoints.size(); i++) {
			ellipse(mappedPoints.get(i).x,mappedPoints.get(i).y,10,10);
			ellipse(width/2,height/2,10,10);
			println(Float.toString(mappedPoints.get(i).x),Float.toString(mappedPoints.get(i).y));
		}
		noLoop();
		println("Finished draw");
	}
	
	
    //include to enable run as java application instead of applet
	
	public static void main(String args[]) {
		PApplet.main(new String[] { "--present", "otlTwitter.TwitterMultiTest" });
	}
}
